package com.zero.guava.samples.Futures;

import com.google.common.util.concurrent.*;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;

/**
 * Futures提供了transform方法
 * 异步转换
 */
public class FuturesTransform {

    private ExecutorService executor;
    private ListeningExecutorService executorService;
    private ListenableFuture<String> listenableFuture;
    private Person person;

    @Before
    public void setUp(){
        executor = Executors.newCachedThreadPool();
        executorService = MoreExecutors.listeningDecorator(executor);
        person = new Person();
    }

    @Test
    public void testFuturesTransform() throws ExecutionException, InterruptedException {

        listenableFuture = executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                return "张三";
            }
        });

        AsyncFunction<String, Person> asyncFunction = new AsyncFunction<String, Person>() {
            @Override
            public ListenableFuture<Person> apply(String input) throws Exception {
                person.setName(input);
                return executorService.submit(new Callable<Person>() {
                    @Override
                    public Person call() throws Exception {
                        return person;
                    }
                });
            }
        };

        ListenableFuture<Person> lf = Futures.transform(listenableFuture, asyncFunction);
        System.out.println(lf.get().getName());
        assertThat(lf.get().getName(), is("张三"));

    }

    @Test
    public void testFuturesFallback() throws ExecutionException, InterruptedException {

        listenableFuture = executorService.submit(new Callable<String>() {
            @Override
            public String call() throws Exception {
                throw new RuntimeException();
            }
        });

        FutureFallback<String> futureFallback = new FutureFallback<String>() {
            @Override
            public ListenableFuture create(Throwable t) throws Exception {
                if (t instanceof RuntimeException) {
                    SettableFuture<String> settableFuture = SettableFuture.create();
                    settableFuture.set("Not Found");
                    return settableFuture;
                }
                throw new Exception(t);
            }
        };

        // Futures.withFallback方法返回了一个ListenableFuture实例，其接收一个listenableFuture参数和futureFallback参数，
        // 如果给定的listenableFuture执行成功，则返回成功的结果，如果失败，则返回 FutureFallback中设置的错误信息。
        ListenableFuture<String> lf = Futures.withFallback(listenableFuture,futureFallback);
        System.out.println(lf.get());
        assertThat(lf.get(), is("Not Found"));
    }
}
